using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using Rhizome.Bindings;
using Rhizome.Contract;
using Rhizome.Model.Validation;
using Rhizome.Internal;

namespace Rhizome.Model
{
	public class PropertyTrigger<TProperty> : TriggerBase<INotifyPropertyChanged>, IForwardEvent
	{
		private BindingProxy _bindingProxy;

		private BindingProxy BindingProxy
		{
			[DebuggerStepThrough]
			get { return _bindingProxy ?? (_bindingProxy = BindingProxy.Create(this, Plant, Property, UseBinding)); }
		}

		protected bool? UseBinding { get; set; }

		/// <summary>
		/// Plant Property name. Must be set before Value
		/// If not set PropertyTrigger will trigged at any Property changes
		/// </summary>
		public string Property { get; set; }

		/// <summary>
		/// Sets Criterion to IfEquals(Property, value) criterion. Must be set after Property
		/// </summary>
		public TProperty Value
		{
#if SILVERLIGHT
            get { return default(TProperty); }
#endif
			set { Criterion = new IfEquals<TProperty>(Property, value); }
		}

		public override void Initialize()
		{
			base.Initialize();

			BindingProxy.PropertyChanged += PlantOnPropertyChanged;
		}

		public override void Cleanup()
		{
			BindingProxy.PropertyChanged -= PlantOnPropertyChanged;

			base.Cleanup();
		}

		private void PlantOnPropertyChanged(object sender, PropertyChangedEventArgs e)
		{
			if (Property.IsNullOrEmpty() || e.PropertyName == Property)
			{
				Trigged();
			}
		}

		#region Validation

		public override IEnumerable<IValidationResult> GetValidationResults()
		{
			return base.GetValidationResults().Concat(InternalValidate());
		}

		private IEnumerable<IValidationResult> InternalValidate()
		{
			if (Plant == null) yield return ValidationResult.PlantIsNull;
			if (Property.IsNullOrEmpty()) yield return ValidationResult.PropertyNotSetWarning;
		}

		#endregion
	}

	public sealed class PropertyTrigger : PropertyTrigger<object>
	{
	}
}